package org.xu.config;

import jodd.util.concurrent.ThreadFactoryBuilder;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.scheduling.annotation.AsyncConfigurer;

import java.util.concurrent.*;

/**
 * @author gang
 */
@Slf4j
@Configuration
public class ExecutorConfig implements AsyncConfigurer {

    static Executor ASYNC_POOL;

    static {
        int corePoolSize = 8;

        ThreadFactory factory = new ThreadFactoryBuilder().setNameFormat("async-pool-%d").get();

        ASYNC_POOL = new ThreadPoolExecutor(corePoolSize, corePoolSize * 6, 1, TimeUnit.MINUTES, new LinkedBlockingDeque<>(10000),
                factory, new ThreadPoolExecutor.AbortPolicy());
    }

    @Bean(name = "taskExecutorPool")
    public Executor taskExecutorPool() {
        log.info("ExecutorConfig|Runtime.getRuntime().availableProcessors(): {}", Runtime.getRuntime().availableProcessors());
        int corePoolSize = 8;

        ThreadFactory factory = new ThreadFactoryBuilder().setNameFormat("task-pool-%d").get();

        return new ThreadPoolExecutor(corePoolSize, corePoolSize * 6, 1, TimeUnit.MINUTES, new LinkedBlockingDeque<>(100),
                factory, new ThreadPoolExecutor.AbortPolicy());
    }

    @Bean(name = "IOTaskExecutorPool")
    public Executor IOTaskExecutorPool() {
        log.info("ExecutorConfig|Runtime.getRuntime().availableProcessors(): {}", Runtime.getRuntime().availableProcessors());
        int corePoolSize = 1;

        ThreadFactory factory = new ThreadFactoryBuilder().setNameFormat("IO-task-pool-%d").get();

        return new ThreadPoolExecutor(corePoolSize, corePoolSize * 2, 10, TimeUnit.MINUTES, new LinkedBlockingDeque<>(10000),
                factory, new ThreadPoolExecutor.AbortPolicy());
    }

    @Primary
    @Bean(name = "asyncExecutorPool")
    public Executor asyncExecutorPool() {
        return ASYNC_POOL;
    }

    @Override
    public Executor getAsyncExecutor() {
        return ASYNC_POOL;
    }
}
